#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gpiod.h>
#include <alsa/asoundlib.h>
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include "config.h"
#include "token.h"
#include "http.h"
#include "record.h"
#include "control.h"

#define GPIO_LINE_K1 9 // K1按钮的GPIO线编号

// 初始化指定的GPIO线为输入模式
struct gpiod_line* init_gpio_line(struct gpiod_chip *chip, int line_num, const char *name) {
    struct gpiod_line *line = gpiod_chip_get_line(chip, line_num);
    if (!line || gpiod_line_request_input(line, name)) {
        perror("初始化GPIO线失败");
        return NULL;
    }
    return line;
}

// 检查按钮状态的变化
int check_button(struct gpiod_line *line, int *last_value) {
    int value = gpiod_line_get_value(line);
    if (value != *last_value) {
        *last_value = value;
        return value;
    }
    return -1;
}

// 读取音频文件
char* load_audio_file(const char* file, size_t* size) {
    FILE* fp = fopen(file, "rb");
    if (!fp) {
        perror(file);
        return NULL;
    }
    fseek(fp, 0, SEEK_END);
    *size = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    char* buffer = (char*)malloc(*size);
    if (!buffer) {
        perror("malloc");
        fclose(fp);
        return NULL;
    }
    fread(buffer, 1, *size, fp);
    fclose(fp);
    return buffer;
}

// 发送请求消息
char* send_request(char* token, char* audio, size_t size) {
    char* url = NULL;
    asprintf(&url, "http://vop.baidu.com/server_api?cuid=hqyj&token=%s", token);
    struct curl_slist* headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: audio/pcm; rate=16000");
    char* response = post(url, headers, audio, &size);
    free(url);
    curl_slist_free_all(headers);
    return response;
}

// 处理服务器返回的响应消息
void process_response(char* response, size_t size) {
    cJSON *json = cJSON_ParseWithLength(response, size);
    if (!json) {
        fprintf(stderr, "解析 JSON 失败: [%s]\n", cJSON_GetErrorPtr());
        return;
    }
    cJSON* err_no = cJSON_GetObjectItem(json, "err_no");
    if (!err_no) {
        fprintf(stderr, "err_no 字段不存在\n");
        cJSON_Delete(json);
        return;
    }
    if (err_no->valueint != 0) {
        cJSON* err_msg = cJSON_GetObjectItem(json, "err_msg");
        if (err_msg) {
            fprintf(stderr, "err_msg: %s\n", err_msg->valuestring);
        }
        cJSON_Delete(json);
        return;
    }
    cJSON *result = cJSON_GetObjectItem(json, "result");
    if (!result) {
        fprintf(stderr, "JSON 格式错误: 找不到'result' 字段\n");
        cJSON_Delete(json);
        return;
    }
    if (cJSON_GetArraySize(result) > 0) {
        cJSON *content = cJSON_GetArrayItem(result, 0);
        printf("result: %s\n", content->valuestring);
    }
    cJSON_Delete(json);
}

// 处理录音的逻辑
int handle_recording(int button_state, snd_pcm_t **capture, snd_pcm_uframes_t *period, char **buffer, FILE **pcm_file) {
    if (button_state == 0 && *capture == NULL) { // 检查按钮按下且未录音
        printf("K1 pressed - 开始录音\n");
        *period = 32; // 设置初始的 period size
        *capture = record_start("hw:0,1", SND_PCM_FORMAT_S16_LE, 1, 16000, period); // 启动录音
        if (!*capture) { // 检查录音启动是否成功
            perror("录音启动失败");
            return -1;
        }
        *buffer = malloc(snd_pcm_frames_to_bytes(*capture, *period)); // 分配缓冲区
        if (!*buffer) {
            perror("缓冲区分配失败");
            record_stop(*capture);
            *capture = NULL;
            return -1;
        }
        *pcm_file = fopen("output.pcm", "wb"); // 打开输出文件
        if (!*pcm_file) { // 检查文件打开是否成功
            perror("打开文件失败");
            free(*buffer);
            record_stop(*capture);
            *capture = NULL;
            return -1;
        }
        printf("录音中...\n");
    } else if (button_state == 1 && *capture != NULL) { // 检查按钮抬起且正在录音
        printf("K1 released - 停止录音\n");
        free(*buffer);         // 释放缓冲区
        fclose(*pcm_file);     // 关闭输出文件
        record_stop(*capture); // 停止录音
        *capture = NULL;       // 重置录音设备指针
        printf("录音停止。\n");
        return 1; // 表示录音已完成
    }
    return 0; // 表示录音进行中
}

// 主函数
int main(void) {
    struct gpiod_chip *chip = gpiod_chip_open_by_label("GPIOF");
    if (!chip) {
        perror("打开GPIO芯片失败");
        return 1;
    }

    struct gpiod_line *line_k1 = init_gpio_line(chip, GPIO_LINE_K1, "key_k1");
    if (!line_k1) {
        gpiod_chip_close(chip);
        return 1;
    }

    int last_value_k1 = gpiod_line_get_value(line_k1);
    snd_pcm_t *capture = NULL;
    snd_pcm_uframes_t period = 0;
    char *buffer = NULL;
    FILE *pcm_file = NULL;
    int recording_done = 0;

    while (!recording_done) {
        int button_k1 = check_button(line_k1, &last_value_k1);

        if (button_k1 != -1) {
            recording_done = handle_recording(button_k1, &capture, &period, &buffer, &pcm_file);
        }

        if (capture != NULL) { // 如果正在录音，继续读取音频数据
            snd_pcm_sframes_t frames = snd_pcm_readi(capture, buffer, period);
            if (frames < 0) {
                fprintf(stderr, "读取音频数据出错: %s\n", snd_strerror(frames)); // 错误处理
                snd_pcm_recover(capture, frames, 0); // 尝试恢复PCM设备
            } else {
                fwrite(buffer, snd_pcm_frames_to_bytes(capture, frames), 1, pcm_file); // 写入音频数据
            }
        }
    }

    gpiod_line_release(line_k1);
    gpiod_chip_close(chip);

    // 读取配置信息，API KEY 和 SECRET KEY
    cJSON *config = read_config("config.json");
    if (!config) {
        printf("config: %s\n", cJSON_Print(config));
        return EXIT_FAILURE;
    }
    cJSON* api_key = cJSON_GetObjectItem(config, "api_key");
    cJSON* secret_key = cJSON_GetObjectItem(config, "secret_key");
    if (!api_key || !secret_key) {
        fprintf(stderr, "配置文件错误: 找不到 'api_key' 或'secret_key' 字段\n");
        cJSON_Delete(config);
        return EXIT_FAILURE;
    }

    // 获取token
    char* token = get_access_token(api_key->valuestring, secret_key->valuestring);
    cJSON_Delete(config);
    if (!token) {
        fprintf(stderr, "获取 token 失败\n");
        return EXIT_FAILURE;
    }


    // 调用百度语音识别 API
    size_t size;
    char* audio = load_audio_file("output.pcm", &size);
    if (!audio) {
        return EXIT_FAILURE;
    }
    char* response = send_request(token, audio, size);
    free(audio);
    free(token);
    if (!response) {
        fprintf(stderr, "调用百度语音识别 API 失败\n");
        return EXIT_FAILURE;
    }

    // 处理服务器返回的响应消息
    process_response(response, size);
    free(response);

    return EXIT_SUCCESS;
}
